/***********************************************************************************************************************
* Copyright (C) . All rights reserved.
***********************************************************************************************************************/
#include "common.h"
#include "userdefine.h"
#include "BAT32G157.h"
#include "system_BAT32G157.h"
#include "easyflash.h"
#include "elog_flash.h"
#include "nr_micro_shell.h"
#include "insdrv_i2c.h"
#include "pd_policy_engine.h"
#include "MultiTimer.h"
#include "sci.h"
#include "sgmdev.h"
#include "sgmdev_pd.h"

#undef LOG_TAG
#define LOG_TAG    "main"
#include "elog.h"

/***********************************************************************************************************************
Global variables and functions
***********************************************************************************************************************/
volatile uint32_t g_ticks; //for delay
volatile uint32_t g_sys_ticks;//for sys tick
#if SHELL_CLI_ENALBE
int shell_parser_flag = 0;
#endif

void delay_1ms(uint32_t n)
{
    g_ticks = n;
    while(g_ticks);
}

#if defined(ELOG_MODULE_ENABLE) && ELOG_MODULE_ENABLE == 1
void test_elog(void) {
    // test log output for all level
    //elog_flash_output_all();
    //elog_flash_flush();
    elog_flash_output_all();
}
#endif

int main()
{
    MD_STATUS status;
    int ret = 0;
    uint32_t msCnt;  // count value of 1ms
//-----------------------------------------------------------------------
// Systick setting 
//-----------------------------------------------------------------------   
    SystemCoreClockUpdate();
    msCnt = SystemCoreClock / 1000;
    SysTick_Config(msCnt);
//-----------------------------------------------------------------------

//-----------------------------------------------------------------------
// Init UART0 for retarget printf/scanf etc. 
//----------------------------------------------------------------------- 
#if 1
    SystemCoreClockUpdate();
    SystemInit();

    status = UART0_Init(SystemCoreClock, 115200);
    INTC_EnableIRQ(SR0_IRQn);
    if (status == MD_ERROR)
        log_e("The baud rate cannot get at the current system clock frequency.\n");

    /* close print buffer */
    setbuf(stdout, NULL);

#if defined(ELOG_MODULE_ENABLE) && ELOG_MODULE_ENABLE == 1
    /* initialize EasyLogger */
    //elog_init();
    if ((easyflash_init() == EF_NO_ERR)&&(elog_init() == ELOG_NO_ERR)) {
        //if (elog_init() == ELOG_NO_ERR) {
        /* set EasyLogger log format */
        elog_set_fmt(ELOG_LVL_ASSERT, ELOG_FMT_ALL);
        elog_set_fmt(ELOG_LVL_ERROR, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
        elog_set_fmt(ELOG_LVL_WARN, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
        elog_set_fmt(ELOG_LVL_INFO, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
        elog_set_fmt(ELOG_LVL_DEBUG, ELOG_FMT_ALL & ~ELOG_FMT_FUNC);
        elog_set_fmt(ELOG_LVL_VERBOSE, ELOG_FMT_ALL & ~ELOG_FMT_FUNC);

        elog_flash_init(); 

        //clean flash
        elog_flash_clean();
        /* start EasyLogger */
        elog_start();
    }
#endif

#if SHELL_CLI_ENALBE
    /*shell */
    shell_init();
#endif
#endif 

    InsDrv_I2c_Init();

    ret = sgmdev_i2c_probe();
    if (ret < 0)
        log_e("fail to probe i2c tcpc sgm41620\n");

    while(1) {
        if (g_pd_isr_flag == true) {
            sgmdev_pd_work_handle();
            g_pd_isr_flag = false;
        }

        multiTimerYield();

        if (sgmdev_is_support_pd())
            tcpc_event_thread();

#if SHELL_CLI_ENALBE
        if (shell_parser_flag) {
            shell_parser_flag = 0;
            shell_parser(&nr_shell, nr_ansi.current_line);
            ansi_clear_current_line(&nr_ansi);
        }
#endif

#if 0
        if (times < 900000)
        {
            times++;
            delay_1us(100);
        }
        else
        {
            times = 0;
            /*for (int k = 0; k < ADC_MAX_NUM;k++)
            {
                sgm41620_get_adc_data(k,&val);
            }*/
        }
#endif
    }
}
/***********************************************************************************************************************
* Function Name: SysTick Handler
* Description  : Decreament the g_ticks value
* Arguments    : None
* Return Value : None
***********************************************************************************************************************/
void SysTick_Handler(void)
{
	g_ticks--;
	g_sys_ticks++;
}

/***********************************************************************************************************************
* Function Name: HardFault_Handler
* Description  : Hard Fault handler to report stacked register values
* Arguments    : None
* Return Value : None
***********************************************************************************************************************/
// Hard Fault handler in C, with stack frame location and LR value
// extracted from the assembly wrapper as input parameters
void hard_fault_handler_c(unsigned int * hardfault_args, unsigned lr_value)
{
	unsigned int stacked_r0;
	unsigned int stacked_r1;
	unsigned int stacked_r2;
	unsigned int stacked_r3;
	unsigned int stacked_r12;
	unsigned int stacked_lr;
	unsigned int stacked_pc;
	unsigned int stacked_psr;
	
	stacked_r0 = ((unsigned long) hardfault_args[0]);
	stacked_r1 = ((unsigned long) hardfault_args[1]);
	stacked_r2 = ((unsigned long) hardfault_args[2]);
	stacked_r3 = ((unsigned long) hardfault_args[3]);
	stacked_r12 = ((unsigned long) hardfault_args[4]);
	stacked_lr = ((unsigned long) hardfault_args[5]);
	stacked_pc = ((unsigned long) hardfault_args[6]);
	stacked_psr = ((unsigned long) hardfault_args[7]);
	
	log_a("[Hard fault handler]\r\n");
	log_a("R0 = %x\r\n", stacked_r0);
	log_a("R1 = %x\r\n", stacked_r1);
	log_a("R2 = %x\r\n", stacked_r2);
	log_a("R3 = %x\r\n", stacked_r3);
	log_a("R12 = %x\r\n", stacked_r12);
	log_a("Stacked LR = %x\r\n", stacked_lr);
	log_a("Stacked PC = %x\r\n", stacked_pc);
	log_a("Stacked PSR = %x\r\n", stacked_psr);
	log_a("Current LR = %x\r\n", lr_value);
	
	while(1); // endless loop
}

/***********************************************************************************************************************
* Function Name: HardFault_Handler
* Description  : Assembly wrapper using Embedded Assembler in Keil MDK
* Arguments    : None
* Return Value : None
***********************************************************************************************************************/
// Hard Fault handler wrapper in assembly
// It extracts the location of stack frame and passes it to handler
// in C as a pointer. We also extract the LR value as second
// parameter.
__asm void HardFault_Handler(void)
{
		MOVS 	r0, #4
		MOV 	r1, LR
		TST 	r0, r1
		BEQ 	stacking_used_MSP
		MRS 	R0, PSP ; first parameter - stacking was using PSP
		B 		get_LR_and_branch
stacking_used_MSP
		MRS 	R0, MSP ; first parameter - stacking was using MSP
get_LR_and_branch
		MOV 	R1, LR ; second parameter is LR current value
		LDR 	R2,=__cpp(hard_fault_handler_c)
		BX 		R2
}

